package com.cskaoyan.market.admin.controller;

import java.io.File;
import java.io.IOException;
import java.time.LocalDateTime;
import java.util.List;
import java.util.UUID;

import javax.servlet.ServletException;
import javax.servlet.annotation.MultipartConfig;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.Part;

import org.apache.commons.lang3.StringUtils;

import com.cskaoyan.market.admin.service.AdminStorageService;
import com.cskaoyan.market.admin.service.MarketStorageService;
import com.cskaoyan.market.admin.service.impl.AdminStorageServiceImpl;
import com.cskaoyan.market.admin.service.impl.MarketStorageServiceImpl;
import com.cskaoyan.market.db.domain.MarketStorage;
import com.cskaoyan.market.util.HttpUtil;
import com.cskaoyan.market.util.JacksonUtil;
import com.cskaoyan.market.util.ResponseUtil;

/**
 * 存储相关控制层。
 *
 * @author BlackFlame33
 * @date 2023/03/21
 **/
@MultipartConfig
@WebServlet("/admin/storage/*")
public class AdminStorageController extends HttpServlet {

    private AdminStorageService adminStorageService = new AdminStorageServiceImpl();
    private MarketStorageService storageService = new MarketStorageServiceImpl();

    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        String requestURI = req.getRequestURI();
        String op = requestURI.replace(req.getContextPath() + "/admin/storage", "");
        switch (op) {
            case "/create":
                createImage(req, resp);
                break;
            case "/update":
                update(req, resp);
                break;
            case "/delete":
                delete(req, resp);
                break;
            default:
                resp.setStatus(404);
        }
    }

    private void createImage(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        // 利用上传时的key值来获取文件的数据
        Part file = req.getPart("file");
        // 文件上传请求，我们可以不用调用mapper来存储数据到数据库，因为上传的这一条记录可能并不会使用
        // storage.setId();
        String name = file.getSubmittedFileName();
        String key = UUID.randomUUID() + name;
        String type = file.getContentType();
        long size = file.getSize();
        // 文件你们打算存储在哪个位置？
        // 1.应用根目录：略有一些小瑕疵，在于执行mvn clean操作之后，图片会被删除，但是在生产环境没有这个问题，所以只是一个开发过程中的小瑕疵
        // 2.任意目录 D:/image/
        // 如果存储在任意路径，那么我们可以做如下设置：
        // 在resources目录下新建一个配置文件，设定key、value键值对
        // 新建listener，读取该配置信息，随后放入context域中
        // 在该处，我们利用context域来获取这些配置信息
        // http://localhost:8083/image/xxxx
        String relativePath = "image/" + key;
        String image = getServletContext().getRealPath(relativePath);
        File f = new File(image);
        if (!f.getParentFile().exists()) {
            // 如果父目录不存在，那么我们创建出父目录
            f.getParentFile().mkdirs();
        }
        file.write(image);
        MarketStorage storage = new MarketStorage();
        storage.setName(name);
        storage.setKey(key);
        storage.setType(type);
        storage.setSize((int)size);
        storage.setUrl("http://localhost:8083/" + relativePath);
        storage.setAddTime(LocalDateTime.now());
        storage.setUpdateTime(LocalDateTime.now());
        storage.setDeleted(false);
        // 存储到db
        try {
            adminStorageService.createImage(storage);
            Thread.sleep(5000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        resp.getWriter().println(JacksonUtil.writeValueAsString(ResponseUtil.ok(storage)));
    }

    private void delete(HttpServletRequest req, HttpServletResponse resp) throws IOException {
        // 获取数据的唯一标识
        String requestBody = HttpUtil.getRequestBody(req);
        String id = JacksonUtil.parseString(requestBody, "id");
        // 参数传递,获取返回值.
        storageService.deleteStorage(id);

        resp.getWriter().println(JacksonUtil.writeValueAsString(ResponseUtil.ok()));

    }

    private void update(HttpServletRequest req, HttpServletResponse resp) throws IOException {

        String requestBody = HttpUtil.getRequestBody(req);
        String name = JacksonUtil.parseString(requestBody, "name");
        String id = JacksonUtil.parseString(requestBody, "id");

        if (StringUtils.isEmpty(name)) {
            resp.getWriter().println(JacksonUtil.writeValueAsString(ResponseUtil.badArgument()));
            return;
        }
        MarketStorage data = storageService.updateStorageName(name, id);

        resp.getWriter().println(JacksonUtil.writeValueAsString(ResponseUtil.ok(data)));
    }

    /**
     * 以下是get的方法分发
     *
     * @param req
     * @param resp
     * @throws ServletException
     * @throws IOException
     */
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        String requestURI = req.getRequestURI();
        String op = requestURI.replace(req.getContextPath() + "/admin/storage/", "");
        if ("list".equals(op)) {
            list(req, resp);
        }
    }

    /**
     * 系统管理中存储对象的查询方法
     *
     * @param req
     * @param resp
     */
    private void list(HttpServletRequest req, HttpServletResponse resp) throws IOException {
        // 解析参数
        String page = req.getParameter("page");
        String limit = req.getParameter("limit");
        String key = req.getParameter("key");
        String name = req.getParameter("name");
        String sort = req.getParameter("sort");
        String order = req.getParameter("order");

        // 各参数的校验
        if (StringUtils.isEmpty(page) || StringUtils.isEmpty(limit)) {
            resp.getWriter().println(JacksonUtil.writeValueAsString(ResponseUtil.badArgument()));
            return;
        }
        // 对于sql语句中的sort和order的值,全部默认值
        if (StringUtils.isEmpty(sort)) {
            sort = "add_time";
        }
        if (StringUtils.isEmpty(order)) {
            order = "desc";
        }
        // service层实现功能
        List<MarketStorage> result = storageService.getList(page, limit, key, name, sort, order);
        // 生成响应体返回
        resp.getWriter().println(JacksonUtil.writeValueAsString(ResponseUtil.okList(result)));
    }
}